package com.tmt.im.wallet.helper;

import com.alibaba.fastjson2.JSONObject;
import com.tmt.im.common.pojo.RechargeHistoryPoJo;
import com.tmt.im.common.pojo.WithdrawHistoryPoJo;
import com.tmt.im.wallet.config.beans.PayProperties;
import com.tmt.springboot.common.annotation._JsonBinding;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.MessageFormat;
import java.util.Arrays;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/10/20 16:14
 * @Version 1.0
 **/
public class WithdrawHelper {

    private static final String GATEWAY_URL_TEMPLATE = "https://{0}/api/applySettlement";

    private static final String ORDER_QUERY_URL_TEMPLATE = "https://{0}/api/settlement?merchantNum={1}&orderNo={2}";

    public static boolean applyWithdraw(WithdrawHistoryPoJo history, String fileName, InputStream dataStream, RestTemplate restTemplate,
                                        PayProperties payProperties, StringBuilder error) {
        String amount = BigDecimal.valueOf(history.getWithdrawAmount() / 100f)
                .setScale(2, RoundingMode.HALF_UP).toPlainString();

        String sign = history.getMerchantNum() + history.getOrderNo() + amount +
                history.getNotifyUrl()
                + history.getChannelCode()
                + history.getBankCardAccount()
                + history.getAccountHolder()
                + history.getUserId()
                + history.getUserNick()
                + payProperties.getMerchantSecretKey();
        sign = DigestUtils.md5Hex(sign);
        history.setSign(sign);

        MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();

        Field[] allFields = history.getClass().getDeclaredFields();
        Arrays.stream(allFields).filter(x -> x.getAnnotation(_JsonBinding.class) != null).forEach(x -> {
            _JsonBinding ann = x.getAnnotation(_JsonBinding.class);
            Object val = null;
            try {
                x.setAccessible(true);
                val = x.get(history);
            } catch (Exception ex) {
            }
            reqParam.add(ann.value(), val);
        });

        reqParam.remove("withdrawAmount");
        reqParam.add("withdrawAmount", amount);

        if (dataStream != null) {
            Resource anotherResource = new InputStreamResource(dataStream);
            reqParam.add("file-data", anotherResource);
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("files", fileName);
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(reqParam, headers);

        String url = MessageFormat.format(GATEWAY_URL_TEMPLATE, payProperties.getPayGateWayHost());
        try {
            ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, JSONObject.class);
            JSONObject jsonResponse = responseEntity.getBody();
            if (jsonResponse != null) {
                int code = jsonResponse.getIntValue("code");
                history.setResultCode(code);
                history.setResponse(jsonResponse.toJSONString());
                if (code == 200) {
                    return true;
                } else {
                    error.append(jsonResponse.getString("msg"));
                }
            }
        } catch (Exception ex) {
            error.append("与支付系统通信失败:").append(ex.getMessage());
        } finally {
            try {
                if (dataStream != null) {
                    dataStream.close();
                }
            } catch (Exception ex) {
            }
        }
        return false;
    }

    /**
     * 查询提现结果
     *
     * @param historyPoJo
     * @param restTemplate
     * @param payProperties
     * @param error
     * @return true——表示提现成功，false——表示提现败或操作未完毕。
     */
    public static boolean queryWithdrawResult(WithdrawHistoryPoJo historyPoJo, RestTemplate restTemplate,
                                              PayProperties payProperties, StringBuilder error) {
        try {
            String url = MessageFormat.format(ORDER_QUERY_URL_TEMPLATE, payProperties.getPayGateWayHost(),
                    payProperties.getMerchantAccount(), historyPoJo.getOrderNo());
            ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, JSONObject.class);
            JSONObject jsonResponse = responseEntity.getBody();
            if (jsonResponse != null) {
                int code = jsonResponse.getIntValue("code");
                if (code == 200) {
                    JSONObject data = jsonResponse.getJSONObject("data");
                    String orderState = data.getString("orderState");
                    int state = Integer.parseInt(orderState);
                    if (state >= 3) {
                        historyPoJo.setConfirmMode(2);
                        historyPoJo.setState(state);
                        if (state == 4) {
                            BigDecimal amount = new BigDecimal(data.getString("amount"));
                            long actualAmount = amount.multiply(BigDecimal.valueOf(100L)).longValue();
                            historyPoJo.setActualAmount(actualAmount);
                        }
                        return true;
                    }
                    switch (orderState) {
                        case "1" -> error.append("审核中");
                        case "2" -> error.append("审核通过");
                        case "3" -> error.append("审核不通过");
                        case "4" -> error.append("已到账");
                        default -> error.append("未识别的订单状态码:").append(orderState);
                    }
                    return false;
                } else {
                    error.append(code).append(":").append(jsonResponse.getString("msg"));
                }
            }
        } catch (Exception ex) {
            error.append("与支付系统通信失败:").append(ex.getMessage());
        }
        return false;
    }
}
